package com.hcc.gateway.app.filter;

import cn.hutool.core.map.MapUtil;
import com.hcc.gateway.app.constant.HccGatewayAppConstant;
import com.hcc.gateway.common.domain.RespBody;
import com.hcc.gateway.common.utils.HttpClientUtils;
import com.hcc.gateway.netty.context.GatewayExchange;
import com.hcc.gateway.netty.context.ReqContext;
import com.hcc.gateway.netty.filter.GatewayFilter;
import com.hcc.gateway.netty.filter.GatewayFilterChain;
import com.hcc.gateway.netty.support.GatewayConstants;
import io.netty.handler.codec.http.HttpMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * HttpRoutingFilter
 *
 * @author shengjun.hu
 * @date 2021/12/28
 */
@Slf4j
@Component("appHttpRoutingFilter")
public class HttpRoutingFilter implements GatewayFilter {

    @Override
    public int getOrder() {
        return 250;
    }

    @Override
    public void filter(GatewayExchange exchange, GatewayFilterChain chain) {
        log.info("进入HttpRoutingFilter !");

        ReqContext reqContext = exchange.getReqContext();
        URI uri = exchange.getAttributeByName(GatewayConstants.GATEWAY_REQUEST_URI_ATTR, URI.class);
        Object paramObj = exchange.getAttributeByName(HccGatewayAppConstant.HCC_REQ_PARAM);

        if (!isHttpRequest(uri.getScheme().toLowerCase())) {
            log.info("不是http协议，跳过HttpRoutingFilter !");
            chain.filter(exchange);
            return;
        }

        HttpMethod method = reqContext.getMethod();
        String url = uri.toString();
        if (HttpMethod.GET.equals(method) || HttpMethod.DELETE.equals(method)) {
            url = this.buildGetUrl(uri.toString(), paramObj);
        }

        RespBody result = HttpClientUtils.method(url, method.name(), reqContext.getContentType(), paramObj);
        exchange.addAttribute(HccGatewayAppConstant.HCC_RESPONSE_OBJECT, result);

        chain.filter(exchange);
    }

    @SuppressWarnings("unchecked")
    private String buildGetUrl(String url, Object paramObj) {
        Map<String, Object> paramMap = (Map<String, Object>) paramObj;
        if (MapUtil.isEmpty(paramMap)) {
            return url;
        }

        List<String> querys = new ArrayList<>();
        paramMap.forEach((k, v) -> {
            if (v == null) {
                return;
            }
            if (Collection.class.isAssignableFrom(v.getClass())) {
                Collection coll = (Collection) v;
                for (Object o : coll) {
                    querys.add(k + "=" + o);
                }
            } else {
                querys.add(k + "=" + v);
            }
        });
        return url.substring(0, url.indexOf("?") + 1) + String.join("&", querys);
    }

    private boolean isHttpRequest(String scheme) {
        return "http".equals(scheme) || "https".equals(scheme);
    }

}
